using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using PCSComMaterials.Inventory.BO;
using PCSComMaterials.Inventory.DS;
using PCSComProduction.DCP.DS;
using PCSComProduction.WorkOrder.DS;
using PCSComUtils.Common;
using PCSComUtils.MasterSetup.DS;
using PCSComUtils.DataContext;
using System.Transactions;
using PCSComUtils.DataAccess;
using PCSComUtils.PCSExc;

namespace PCSComProduction.WorkOrder.BO
{
    public class MultiWOIssueMaterialBO
    {
        #region IMultiWOIssueMaterialBO Members

        public DataSet GetWorkingTime()
        {
            PRO_ShiftPatternDS dsShiftPattern = new PRO_ShiftPatternDS();
            return dsShiftPattern.GetWorkingTime();
        }

        public int InsertIssueMaterial(PRO_IssueMaterialMaster issueMaster)
        {
            const string methodName = "PCSComProduction.WorkOrder.BO.InsertIssueMaterial()";
            try
            {
                using (var trans = new TransactionScope())
                {
                    using (var db = new PCSDataContext(Utils.Instance.ConnectionString))
                    {
                        var serverDate = db.GetServerDate();
                        var tranTypeId = db.MST_TranTypes.FirstOrDefault(t => t.Code == TransactionTypeEnum.PROIssueMaterial.ToString()).TranTypeID;

                        db.PRO_IssueMaterialMasters.InsertOnSubmit(issueMaster);
                        db.SubmitChanges();

                        foreach (var issueDetail in issueMaster.PRO_IssueMaterialDetails)
                        {
                            #region subtract from source cache

                            #region bin cache

                            var sourceBin = db.IV_BinCaches.FirstOrDefault(e => e.LocationID == issueDetail.LocationID && e.BinID == issueDetail.BinID && e.ProductID == issueDetail.ProductID);
                            if (sourceBin == null || sourceBin.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, sourceBin == null ? 0 : sourceBin.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }

                            sourceBin.OHQuantity = sourceBin.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region location cache

                            var sourceLocation = db.IV_LocationCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.LocationID == issueDetail.LocationID && e.ProductID == issueDetail.ProductID);
                            if (sourceLocation == null || sourceLocation.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, sourceLocation == null ? 0 : sourceLocation.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }
                            sourceLocation.OHQuantity = sourceLocation.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region master location cache

                            var sourceMasLocation = db.IV_MasLocCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.ProductID == issueDetail.ProductID);
                            if (sourceMasLocation == null || sourceMasLocation.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, sourceMasLocation == null ? 0 : sourceMasLocation.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }
                            sourceMasLocation.OHQuantity = sourceMasLocation.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region Transaction history

                            var sourceHistory = new MST_TransactionHistory
                                                    {
                                                        CCNID = issueMaster.CCNID,
                                                        StockUMID = issueDetail.StockUMID,
                                                        MasterLocationID = issueMaster.MasterLocationID,
                                                        ProductID = issueDetail.ProductID,
                                                        LocationID = issueDetail.LocationID,
                                                        BinID = issueDetail.BinID,
                                                        RefMasterID = issueMaster.IssueMaterialMasterID,
                                                        RefDetailID = issueDetail.IssueMaterialDetailID,
                                                        PostDate = issueMaster.PostDate,
                                                        TransDate = serverDate,
                                                        Quantity = -issueDetail.CommitQuantity,
                                                        UserName = SystemProperty.UserName,
                                                        TranTypeID = tranTypeId,
                                                        BinCommitQuantity = sourceBin.CommitQuantity,
                                                        BinOHQuantity = sourceBin.OHQuantity,
                                                        IssuePurposeID = issueMaster.IssuePurposeID,
                                                        LocationCommitQuantity = sourceLocation.CommitQuantity,
                                                        LocationOHQuantity = sourceLocation.OHQuantity,
                                                        MasLocCommitQuantity = sourceMasLocation.CommitQuantity,
                                                        MasLocOHQuantity = sourceMasLocation.OHQuantity
                                                    };
                            db.MST_TransactionHistories.InsertOnSubmit(sourceHistory);

                            #endregion

                            #endregion

                            #region add to destination cache

                            #region bin cache

                            var destBin = db.IV_BinCaches.FirstOrDefault(e => e.LocationID == issueMaster.ToLocationID && e.BinID == issueMaster.ToBinID && e.ProductID == issueDetail.ProductID);
                            if (destBin != null)
                            {
                                destBin.OHQuantity = destBin.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                destBin = new IV_BinCache
                                              {
                                                  BinID = issueMaster.ToBinID.GetValueOrDefault(0),
                                                  CCNID = issueMaster.CCNID,
                                                  LocationID = issueMaster.ToLocationID.GetValueOrDefault(0),
                                                  MasterLocationID = issueMaster.MasterLocationID,
                                                  ProductID = issueDetail.ProductID,
                                                  OHQuantity = issueDetail.CommitQuantity
                                              };
                                db.IV_BinCaches.InsertOnSubmit(destBin);
                            }

                            #endregion

                            #region location cache

                            var destLocation = db.IV_LocationCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.LocationID == issueMaster.ToLocationID && e.ProductID == issueDetail.ProductID);
                            if (destLocation != null)
                            {
                                destLocation.OHQuantity = destLocation.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                destLocation = new IV_LocationCache
                                                   {
                                                       CCNID = issueMaster.CCNID,
                                                       LocationID = issueMaster.ToLocationID.GetValueOrDefault(0),
                                                       MasterLocationID = issueMaster.MasterLocationID,
                                                       ProductID = issueDetail.ProductID,
                                                       OHQuantity = issueDetail.CommitQuantity
                                                   };
                                db.IV_LocationCaches.InsertOnSubmit(destLocation);
                            }

                            #endregion

                            #region master location cache

                            var destMasLocation = db.IV_MasLocCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.ProductID == issueDetail.ProductID);
                            if (destMasLocation != null)
                            {
                                destMasLocation.OHQuantity = destMasLocation.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                destMasLocation = new IV_MasLocCache
                                                      {
                                                          CCNID = issueMaster.CCNID,
                                                          MasterLocationID = issueMaster.MasterLocationID,
                                                          ProductID = issueDetail.ProductID,
                                                          OHQuantity = issueDetail.CommitQuantity
                                                      };
                                db.IV_MasLocCaches.InsertOnSubmit(destMasLocation);
                            }

                            #endregion

                            #region Transaction history

                            var destHistory = new MST_TransactionHistory
                                                  {
                                                      CCNID = issueMaster.CCNID,
                                                      StockUMID = issueDetail.StockUMID,
                                                      MasterLocationID = issueMaster.MasterLocationID,
                                                      ProductID = issueDetail.ProductID,
                                                      LocationID = issueMaster.ToLocationID,
                                                      BinID = issueMaster.ToBinID,
                                                      RefMasterID = issueMaster.IssueMaterialMasterID,
                                                      RefDetailID = issueDetail.IssueMaterialDetailID,
                                                      PostDate = issueMaster.PostDate,
                                                      TransDate = serverDate,
                                                      Quantity = issueDetail.CommitQuantity,
                                                      UserName = SystemProperty.UserName,
                                                      TranTypeID = tranTypeId,
                                                      BinCommitQuantity = destBin.CommitQuantity,
                                                      BinOHQuantity = destBin.OHQuantity,
                                                      IssuePurposeID = issueMaster.IssuePurposeID,
                                                      LocationCommitQuantity = destLocation.CommitQuantity,
                                                      LocationOHQuantity = destLocation.OHQuantity,
                                                      MasLocCommitQuantity = destMasLocation.CommitQuantity,
                                                      MasLocOHQuantity = destMasLocation.OHQuantity
                                                  };
                            db.MST_TransactionHistories.InsertOnSubmit(destHistory);

                            #endregion

                            #endregion

                            db.SubmitChanges();
                        }

                        db.SubmitChanges();
                        trans.Complete();
                        return issueMaster.IssueMaterialMasterID;
                    }
                }
            }
            catch (PCSBOException ex)
            {
                if (ex.mCode == ErrorCode.SQLDUPLICATE_KEYCODE)
                    throw new PCSDBException(ErrorCode.DUPLICATE_KEY, methodName, ex);
                if (ex.mCode == ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE)
                    throw;
                throw new PCSDBException(ErrorCode.ERROR_DB, methodName, ex);
            }
        }
        
        /// <summary>
        /// GetToLocationCode
        /// </summary>
        /// <param name="pintToLocationID"></param>
        /// <returns></returns>
        /// <author>Trada</author>
        /// <date>Thursday, October 27 2005</date>
        public object GetToLocationCode(int pintToLocationID)
        {
            MST_LocationDS dsMST_Location = new MST_LocationDS();
            return dsMST_Location.GetObjectVO(pintToLocationID);
        }

        /// <summary>
        /// GetIssuePurpose
        /// </summary>
        /// <param name="pintIssuePurposeID"></param>
        /// <returns></returns>
        /// <author>Trad</author>
        /// <Date>Wednesday, Nov 30 2005</Date>
        public object GetIssuePurpose(int pintIssuePurposeID)
        {
            PRO_IssuePurposeDS dsPRO_IssuePurpose = new PRO_IssuePurposeDS();
            return dsPRO_IssuePurpose.GetObjectVO(pintIssuePurposeID);
        }

        /// <summary>
        /// GetToBinCode
        /// </summary>
        /// <param name="pintToBinID"></param>
        /// <returns></returns>
        /// <author>Trada</author>
        /// <date>Thursday, October 27 2005</date>
        public object GetToBinCode(int pintToBinID)
        {
            MST_BINDS dsBin = new MST_BINDS();
            return dsBin.GetObjectVO(pintToBinID);
        }
        
        /// <summary>
        /// Get Detail Data, overloaded by Tuan TQ. Get Available Qty by Post Date
        /// </summary>
        /// <param name="pdtmPostDate"></param>
        /// <param name="pintMasterID"></param>
        /// <param name="pintCCNID"></param>
        /// <param name="ppintMasterLocationID"></param>
        /// <returns></returns>
        /// <author> Tuan TQ. 10 Jan, 2006</author>
        public DataSet GetDetailData(DateTime pdtmPostDate, int pintMasterID, int pintCCNID, int ppintMasterLocationID)
        {

            PRO_IssueMaterialDetailDS objPRO_IssueMaterialDetailDS = new PRO_IssueMaterialDetailDS();
            return objPRO_IssueMaterialDetailDS.GetDetailData(pintMasterID);
        }

        public object GetMasterLocationVO(int ppintMasterLocationID)
        {
            MST_MasterLocationDS dsMST_MasterLocationDS = new MST_MasterLocationDS();
            return dsMST_MasterLocationDS.GetObjectVO(ppintMasterLocationID);
        }

        /// <summary>
        /// Get needed quantity
        /// </summary>
        /// <returns></returns>
        public DataTable GetNeededQuantity(int pintMasterLocationID)
        {
            PRO_IssueMaterialDetailDS dsIssueMaterialDetail = new PRO_IssueMaterialDetailDS();
            return dsIssueMaterialDetail.GetNeededQuantity(pintMasterLocationID);
        }

        /// <summary>
        /// Get commited quantity
        /// </summary>
        /// <returns></returns>
        public List<PRO_IssueMaterialDetail> GetCommitedQuantity(int pintMasterLocationID, List<int> productIds)
        {
            var db = new PCSDataContext(Utils.Instance.ConnectionString);
            return db.PRO_IssueMaterialDetails.Where(b => b.MasterLocationID == pintMasterLocationID && productIds.Contains(b.ProductID)).ToList();
        }

        /// <summary>
        /// Get Cached QA quantity
        /// </summary>
        /// <param name="pintCCNID"></param>
        /// <param name="pintMasterLocationID"></param>
        /// <returns></returns>
        public DataTable GetCachedQAStatus(int pintCCNID, int pintMasterLocationID)
        {
            PRO_IssueMaterialDetailDS dsIssueMaterialDetail = new PRO_IssueMaterialDetailDS();
            return dsIssueMaterialDetail.GetCachedQAStatus(pintCCNID, pintMasterLocationID);
        }

        public List<IV_BinCache> GetAvailableQuantity(int ccnId, int masterLocationId, List<int> productIds)
        {
            var db = new PCSDataContext(Utils.Instance.ConnectionString);
            return db.IV_BinCaches.Where(b => b.CCNID == ccnId && b.MasterLocationID == masterLocationId && productIds.Contains(b.ProductID)).ToList();
        }

        public DataTable GetAvailableQuantityByPostDate(DateTime pdtmPostDate, int pintCCNID, int pintMasterLocationID, string pstrProductIDs)
        {
            PRO_IssueMaterialDetailDS dsIssueMaterialDetail = new PRO_IssueMaterialDetailDS();
            return dsIssueMaterialDetail.GetAvailableQuantityByPostDate(pdtmPostDate, pintCCNID, pintMasterLocationID, pstrProductIDs);
        }

        /// <summary>
        /// This method is used to get the available quantity in the inventory
        /// 
        /// </summary>
        /// <param name="pintBinID"></param>
        /// <param name="pintLocationID"></param>
        /// <param name="ppintMasterLocationID"></param>
        /// <param name="pintCCNID"></param>
        /// <param name="pintProductID"></param>
        /// <param name="pstrLot"></param>
        /// <param name="pstrSerial"></param>
        /// <returns></returns>
        public decimal GetAvailableQuantity(int pintBinID, int pintLocationID, int ppintMasterLocationID, int pintCCNID, int pintProductID, string pstrLot, string pstrSerial)
        {
            decimal decQuantity = 0;

            //in case of there is a serial ==> we only check for the remain of serial
            if ((pstrSerial != null) && (pstrLot != null) && (pstrSerial != String.Empty) && (pstrLot != String.Empty))
            {
                IV_ItemSerialDS dsSerial = new IV_ItemSerialDS();
                return dsSerial.CheckRemain(pstrSerial, pintCCNID, pintProductID) ? Decimal.One : 0;
            }

            // if BinID <> 0 then we get available quantity from BinCache
            if ((ppintMasterLocationID > 0) && (pintLocationID > 0) && (pintBinID > 0))
            {
                IV_BinCacheDS dsBinCache = new IV_BinCacheDS();
                decQuantity = !string.IsNullOrEmpty(pstrLot) ? dsBinCache.GetAvailableQuantityByLot(pintCCNID, ppintMasterLocationID, pintLocationID, pintBinID, pstrLot, pintProductID) : dsBinCache.GetAvailableQuantity(pintCCNID, ppintMasterLocationID, pintLocationID, pintBinID, pintProductID);
            }
                // else get available quantity from LocationCache
            else if ((ppintMasterLocationID > 0) && (pintLocationID > 0))
            {
                IV_LocationCacheDS dsLocationCache = new IV_LocationCacheDS();
                decQuantity = !string.IsNullOrEmpty(pstrLot) ? dsLocationCache.GetAvailableQuantityByLot(pintCCNID, ppintMasterLocationID, pintLocationID, pstrLot, pintProductID) : dsLocationCache.GetAvailableQuantityByLocation(pintCCNID, ppintMasterLocationID, pintLocationID, pintProductID);
            }
            else if (ppintMasterLocationID > 0)
            {
                IV_MasLocCacheDS dsMasLocCache = new IV_MasLocCacheDS();
                decQuantity = !string.IsNullOrEmpty(pstrLot)
                                  ? dsMasLocCache.GetAvailableQuantityByLot(pintCCNID, ppintMasterLocationID, pstrLot,
                                                                            pintProductID)
                                  : dsMasLocCache.GetAvailableQuantity(pintCCNID, ppintMasterLocationID, pintProductID);
            }
            return decQuantity;
        }

        /// <summary>
        /// 
        /// </summary>		
        /// <param name="pstrLocationCode"></param>
        /// <returns>MST_LocationVO</returns>
        public string GetLocationNameByLocationCode(string pstrLocationCode)
        {
            // UNDONE: try catch
            MST_LocationDS objDS = new MST_LocationDS();
            return objDS.GetNameFromCode(pstrLocationCode);
        }

        /// <summary>
        /// Delete transaction
        /// </summary>
        /// <param name="issueMasterId"></param>
        public void DeleteTransaction(int issueMasterId)
        {
            const string methodName = "PCSComProduction.WorkOrder.BO.MultiWOIssueMaterialBO.DeleteTransaction()";
            try
            {
                using (var trans = new TransactionScope())
                {
                    using (var db = new PCSDataContext(Utils.Instance.ConnectionString))
                    {
                        var tranTypeId = db.MST_TranTypes.FirstOrDefault(t => t.Code == TransactionTypeEnum.PROIssueMaterial.ToString()).TranTypeID;
                        var deleteTranTypeId = db.MST_TranTypes.FirstOrDefault(t => t.Code == TransactionTypeEnum.DeleteTransaction.ToString()).TranTypeID;
                        var serverDate = db.GetServerDate();

                        #region PRO_IssueMaterialMasters

                        var issueMaster = db.PRO_IssueMaterialMasters.FirstOrDefault(e => e.IssueMaterialMasterID == issueMasterId);
                        if (issueMaster == null)
                            return;

                        #endregion

                        #region old transaction history to be updated

                        var oldSourceHistory = db.MST_TransactionHistories.Where(e => e.RefMasterID == issueMasterId && e.TranTypeID == tranTypeId);
                        foreach (var history in oldSourceHistory)
                        {
                            // mark as delete transaction
                            history.TranTypeID = deleteTranTypeId;
                            history.UserName = SystemProperty.UserName;
                        }

                        #endregion

                        #region cache data

                        foreach (var issueDetail in issueMaster.PRO_IssueMaterialDetails)
                        {
                            #region subtract from destionation cache

                            #region bin cache

                            var destBin = db.IV_BinCaches.FirstOrDefault(e => e.LocationID == issueMaster.ToLocationID && e.BinID == issueMaster.ToBinID && e.ProductID == issueDetail.ProductID);
                            if (destBin == null || destBin.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, destBin == null ? 0 : destBin.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }
                            destBin.OHQuantity = destBin.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region location cache

                            var destLocation = db.IV_LocationCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.LocationID == issueMaster.ToLocationID && e.ProductID == issueDetail.ProductID);
                            if (destLocation == null || destLocation.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, destLocation == null ? 0 : destLocation.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }
                            destLocation.OHQuantity = destLocation.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region master location cache

                            var destMasLocation = db.IV_MasLocCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.ProductID == issueDetail.ProductID);
                            if (destMasLocation == null || destMasLocation.OHQuantity.GetValueOrDefault(0) < issueDetail.CommitQuantity)
                            {
                                var productError = new Hashtable
                                                       {
                                                           { ITM_ProductTable.PRODUCTID_FLD, issueDetail.ProductID },
                                                           { IV_BinCacheTable.OHQUANTITY_FLD, destMasLocation == null ? 0 : destMasLocation.OHQuantity.GetValueOrDefault(0) }
                                                       };
                                throw new PCSBOException(ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE, issueDetail.ITM_Product.Code, new Exception(), productError);
                            }
                            destMasLocation.OHQuantity = destMasLocation.OHQuantity.GetValueOrDefault(0) - issueDetail.CommitQuantity;

                            #endregion

                            #region Transaction history

                            var destHistory = new MST_TransactionHistory
                            {
                                CCNID = issueMaster.CCNID,
                                StockUMID = issueDetail.StockUMID,
                                MasterLocationID = issueMaster.MasterLocationID,
                                ProductID = issueDetail.ProductID,
                                LocationID = issueMaster.ToLocationID,
                                BinID = issueMaster.ToBinID,
                                RefMasterID = issueMaster.IssueMaterialMasterID,
                                RefDetailID = issueDetail.IssueMaterialDetailID,
                                PostDate = issueMaster.PostDate,
                                TransDate = serverDate,
                                Quantity = -issueDetail.CommitQuantity,
                                UserName = SystemProperty.UserName,
                                TranTypeID = tranTypeId,
                                BinCommitQuantity = destBin.CommitQuantity,
                                BinOHQuantity = destBin.OHQuantity,
                                IssuePurposeID = issueMaster.IssuePurposeID,
                                LocationCommitQuantity = destLocation.CommitQuantity,
                                LocationOHQuantity = destLocation.OHQuantity,
                                MasLocCommitQuantity = destMasLocation.CommitQuantity,
                                MasLocOHQuantity = destMasLocation.OHQuantity
                            };
                            db.MST_TransactionHistories.InsertOnSubmit(destHistory);

                            #endregion

                            #endregion

                            #region add to source cache

                            #region bin cache

                            var sourceBin = db.IV_BinCaches.FirstOrDefault(e => e.LocationID == issueDetail.LocationID && e.BinID == issueDetail.BinID && e.ProductID == issueDetail.ProductID);
                            if (sourceBin != null)
                            {
                                sourceBin.OHQuantity = sourceBin.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                sourceBin = new IV_BinCache
                                {
                                    BinID = issueDetail.BinID.GetValueOrDefault(0),
                                    CCNID = issueMaster.CCNID,
                                    LocationID = issueDetail.LocationID,
                                    MasterLocationID = issueMaster.MasterLocationID,
                                    ProductID = issueDetail.ProductID,
                                    OHQuantity = issueDetail.CommitQuantity
                                };
                                db.IV_BinCaches.InsertOnSubmit(sourceBin);
                            }

                            #endregion

                            #region location cache

                            var sourceLocation = db.IV_LocationCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.LocationID == issueDetail.LocationID && e.ProductID == issueDetail.ProductID);
                            if (sourceLocation != null)
                            {
                                sourceLocation.OHQuantity = sourceLocation.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                sourceLocation = new IV_LocationCache
                                {
                                    CCNID = issueMaster.CCNID,
                                    LocationID = issueDetail.LocationID,
                                    MasterLocationID = issueMaster.MasterLocationID,
                                    ProductID = issueDetail.ProductID,
                                    OHQuantity = issueDetail.CommitQuantity
                                };
                                db.IV_LocationCaches.InsertOnSubmit(sourceLocation);
                            }

                            #endregion

                            #region master location cache

                            var sourceMasLocation = db.IV_MasLocCaches.FirstOrDefault(e => e.MasterLocationID == issueMaster.MasterLocationID && e.ProductID == issueDetail.ProductID);
                            if (sourceMasLocation != null)
                            {
                                sourceMasLocation.OHQuantity = sourceMasLocation.OHQuantity.GetValueOrDefault(0) + issueDetail.CommitQuantity;
                            }
                            else
                            {
                                // create new record
                                sourceMasLocation = new IV_MasLocCache
                                {
                                    CCNID = issueMaster.CCNID,
                                    MasterLocationID = issueMaster.MasterLocationID,
                                    ProductID = issueDetail.ProductID,
                                    OHQuantity = issueDetail.CommitQuantity
                                };
                                db.IV_MasLocCaches.InsertOnSubmit(sourceMasLocation);
                            }

                            #endregion

                            #region Transaction history

                            var sourceHistory = new MST_TransactionHistory
                            {
                                CCNID = issueMaster.CCNID,
                                StockUMID = issueDetail.StockUMID,
                                MasterLocationID = issueMaster.MasterLocationID,
                                ProductID = issueDetail.ProductID,
                                LocationID = issueDetail.LocationID,
                                BinID = issueDetail.BinID,
                                RefMasterID = issueMaster.IssueMaterialMasterID,
                                RefDetailID = issueDetail.IssueMaterialDetailID,
                                PostDate = issueMaster.PostDate,
                                TransDate = serverDate,
                                Quantity = issueDetail.CommitQuantity,
                                UserName = SystemProperty.UserName,
                                TranTypeID = tranTypeId,
                                BinCommitQuantity = sourceBin.CommitQuantity,
                                BinOHQuantity = sourceBin.OHQuantity,
                                IssuePurposeID = issueMaster.IssuePurposeID,
                                LocationCommitQuantity = sourceLocation.CommitQuantity,
                                LocationOHQuantity = sourceLocation.OHQuantity,
                                MasLocCommitQuantity = sourceMasLocation.CommitQuantity,
                                MasLocOHQuantity = sourceMasLocation.OHQuantity
                            };
                            db.MST_TransactionHistories.InsertOnSubmit(sourceHistory);

                            #endregion

                            #endregion

                            db.PRO_IssueMaterialDetails.DeleteOnSubmit(issueDetail);
                        }
                        #endregion

                        db.PRO_IssueMaterialMasters.DeleteOnSubmit(issueMaster);
                        db.SubmitChanges();
                        trans.Complete();
                    }
                }
            }
            catch (PCSBOException ex)
            {
                if (ex.mCode == ErrorCode.SQLDUPLICATE_KEYCODE)
                    throw new PCSDBException(ErrorCode.DUPLICATE_KEY, methodName, ex);
                if (ex.mCode == ErrorCode.MESSAGE_NOT_ENOUGH_COMPONENT_TO_COMPLETE)
                    throw;
                throw new PCSDBException(ErrorCode.ERROR_DB, methodName, ex);
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pintIssueMasterID"></param>
        /// <returns></returns>
        public DataTable GetMasterIssue(int pintIssueMasterID)
        {
            return (new PRO_IssueMaterialMasterDS()).GetMasterIssue(pintIssueMasterID);
        }

        public DataSet GetLocAndBin(string pstrLocs, string pstrBins)
        {
            return (new PRO_IssueMaterialMasterDS()).GetLocAndBin(pstrLocs, pstrBins);
        }
    }
}
